package com.dtflys.easyel.compile;

import com.dtflys.easyel.utils.ThrowUtils;
import com.dtflys.easyel.exception.EasyElParseException;
import org.antlr.v4.runtime.*;

import java.util.ArrayList;
import java.util.List;


/**
 * @author gongjun[jun.gong@thebeastshop.com]
 * @since v1.0.0
 */
public class EasyElErrorListener extends BaseErrorListener {

    private List<EasyElParseError> errors = new ArrayList<>();

    private final EasyElSource source;

    private int maxErrorNumber = 10;

    public EasyElErrorListener(EasyElSource source, Integer maxErrorNumber) {
        this.source = source;
        if (maxErrorNumber != null) {
            this.maxErrorNumber = maxErrorNumber;
        }
    }

    @Override
    public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
        addError(line, charPositionInLine, charPositionInLine + 1, msg);
    }

    public void addError(ParserRuleContext ctx, String msg) {
        Token start = ctx.start;
        Token stop = ctx.stop;
        addError(start.getLine(), start.getCharPositionInLine(),
                stop.getCharPositionInLine() + stop.getText().length(),
                msg);
    }

    public void addError(int line, int startColumn, int endColumn, String msg) {
        EasyElSourcePosition position = new EasyElSourcePosition(line, line, startColumn, endColumn);
        EasyElParseError error = new EasyElParseError(position, msg);
        errors.add(error);
        if (errors.size() >= maxErrorNumber) {
            throwParseException();
        }
    }

    public boolean hasError() {
        return !errors.isEmpty();
    }

    private void throwParseException() {
        RuntimeException ex = new EasyElParseException(source, errors);
        ThrowUtils.throwWithoutEasyElPackages(ex);
    }

    public void interruptIfHasError() {
        if (hasError()) {
            throwParseException();
        }
    }
}
